#pragma once

#include "thread.h"
#include "fiber.h"
#include <vector>
#include <mutex>

namespace sylar{
class Sheduler{
    struct ShedulerTask;
private:
    std::string _name;
    std::mutex _mtx;
    std::vector<std::shared_ptr<Thread>> _threads;
    std::vector<int> _threadsId;
    std::vector<ShedulerTask> _Tasks;
    std::atomic<uint64_t> _threadscount{0}; //线程数目
    std::atomic<uint64_t> _activethreadscount{0}; //活跃线程数目
    std::atomic<uint64_t> _idlethreadscount{0}; //待机线程数目
    bool _usecaller;//主线程是否为工作线程
    //如果是的话，需要额外创建调度协程,主线程id
    std::shared_ptr<Fiber> _shedulerfiber;
    int _rootthreadid;
    //是否能关闭
    bool _isstopping = false;
private:
    struct ShedulerTask{
        std::shared_ptr<Fiber> _fiber;
        //Fiber* _fiber;
        func_t _func;
        int _thread; //此任务需要哪个线程执行
        ShedulerTask(){
            _fiber=nullptr;
            _func = nullptr;
            _thread= -1;
        }
        ShedulerTask(std::shared_ptr<Fiber> fiber,int thread){
            _fiber = fiber;
            _thread = thread;
        }
        ShedulerTask(std::shared_ptr<Fiber>* fiber,int thread){
            _fiber.swap(*fiber);
            _thread=thread;
        }
        ShedulerTask(func_t func,int thread){
            _func = func;
            _thread= thread;
        }
        ShedulerTask(func_t* func,int thread){
            _func.swap(*func);
            _thread=thread;
        }
        void reset(){
            _fiber=nullptr;
            _func = nullptr;
            _thread = -1;
        }
    
    };
public:
    Sheduler(ssize_t threads = 1,bool use_caller =true,std::string name="Sheduler");
    ~Sheduler();
    const std::string getname() const { return _name;}
public:
    static Sheduler* getthis();//获取正在运行的协调器
    void setthis(); //设置协调器
    template<class T> //此时的T任务可能是函数，也可能是协程
    void push(T f,int thread = -1){
        bool need_tickle; //标记队列是否为空，是否需要唤醒线程
        {
            std::lock_guard<std::mutex> lock(_mtx);
            need_tickle = _Tasks.empty();//如果任务队列为空，那么所以线程都是待机状态，需要唤醒
            ShedulerTask task(f,thread);
            if(task._fiber || task._func){
                _Tasks.push_back(task);
            }
        }
        if(need_tickle){
            tickle();
        }
    }
    void start(); //启动线程和协程
    void stop();
protected:
    virtual void tickle(); //唤醒线程
    void run();  //线程的执行入口函数
    virtual void idle(); //空闲时，线程执行这个函数进入休眠
    virtual bool can_stop(); //是否能关闭
protected:
    bool hasidlthreads() { return _idlethreadscount > 0;};
};
}